package com.fyz.aaronfjava.common.config;

import com.fyz.aaronfjava.common.aop.MethodLoggingAspect;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.lang.reflect.Method;
import java.util.Arrays;


/**
 * @Author：AaronF
 * @Date：2024/1/31 9:45
 * @description spring线程池配置 @EnableAsync表示开启对@Async注解的支持
 */
@Configuration
@EnableAsync
@ConfigurationProperties(prefix = "spring.async")
public class SpringAsyncConfig implements AsyncConfigurer {

    private static final Logger log = LoggerFactory.getLogger(SpringAsyncConfig.class);


    /**
     * 核心线程数
     */
    private int coreSize = 2;
    /**
     * 最大线程数
     */
    private int maxSize = 10;
    /**
     * 队列长度
     */
    private int queueSize = 200;

    @Bean("asyncTaskExecutor")
    @Override
    public AsyncTaskExecutor getAsyncExecutor() {
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        threadPoolTaskExecutor.setCorePoolSize(coreSize);
        threadPoolTaskExecutor.setMaxPoolSize(maxSize);
        threadPoolTaskExecutor.setQueueCapacity(queueSize);
        threadPoolTaskExecutor.setThreadNamePrefix("AARON-F-ASYNC-TASK-");
        threadPoolTaskExecutor.setRejectedExecutionHandler((r, poolExecutor) -> log.warn("队列已满，拒绝执行"));
        threadPoolTaskExecutor.initialize();
        return threadPoolTaskExecutor;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new CustomAsyncUncaughtExceptionHandler();
    }

    /**
     * 自定义异步异常处理器
     */
    private static class CustomAsyncUncaughtExceptionHandler implements AsyncUncaughtExceptionHandler {
        @Override
        public void handleUncaughtException(Throwable ex, Method method, Object... params) {
            log.warn("CustomAsyncUncaughtExceptionHandler,class:{}, method: {}, params: {}, error: {}",
                    method.getDeclaringClass().getSimpleName(), method.getName(), Arrays.toString(params),
                    ex.getMessage());
        }
    }

    public void setCoreSize(int coreSize) {
        this.coreSize = coreSize;
    }

    public void setMaxSize(int maxSize) {
        this.maxSize = maxSize;
    }

    public void setQueueSize(int queueSize) {
        this.queueSize = queueSize;
    }
}
